#ifndef VEC4_H_
#define VEC4_H_

#include "Vec3.h"

class File;

template <typename T>
class Vec4
{
public:
    /* Default ctr*/
    Vec4() : 
    m_w(1), m_x(0), m_y(0), m_z(0) 
    {}  
    /* Copy Constructor */
    Vec4(const Vec4& v) : 
    m_w(v.GetW()), m_x(v.GetX()), m_y(v.GetY()), m_z(v.GetZ())
    {}
    /* Overloaded ctr  (float) */
    Vec4(const Vec3f& v) :
    m_w(1), m_x(v.GetX()), m_y(v.GetY()), m_z(v.GetZ()) 
    {}
    /* Overloaded ctr  (int)   */
    Vec4(const Vec3i& v) :
    m_w(1), m_x(v.GetX()), m_y(v.GetY()), m_z(v.GetZ()) 
    {}
    /* Overloaded ctr */
    Vec4(const T x, const T y, const T z, const T w = 1) :
    m_w(w), m_x(x), m_y(y), m_z(z) 
    {}

    /* Const Get Functions. */
    T GetW() const
    {
        return m_w;
    }
    T GetX() const
    {
        return m_x;
    }
    T GetY() const
    {
        return m_y;
    }
    T GetZ() const
    {
        return m_z;
    }
    /* Non Const Get Functions. */
    T& GetW()
    {
        return m_w;
    }
    T& GetX()
    {
        return m_x;
    }
    T& GetY()
    {
        return m_y;
    }
    T& GetZ()
    {
        return m_z;
    }
    /* Set Functions. */
    void SetW ( const T w)
    {
        m_w = w;
    }
    void SetX ( const T x)
    {
        m_x = x;
    }
    void SetY ( const T y)
    {
        m_y = y;
    }
    void SetZ ( const T z)
    {
        m_z = z;
    }
    void SetStats(const T x, const T y, const T z, const T w = 1)
    {
        m_w = w;
        m_x = x;
        m_y = y;
        m_z = z;
    }

    /* Returns the Vec3 corresponding to the homogeneous coordinate
     *  formed by the Vec 4
     */
    Vec3<T> GetVec3() const
    {
        return Vec3<T>( m_x / m_w,
                        m_y / m_w,
                        m_z / m_w);
    }

    /* Index operators returning by value or reference. 
     * depending on constness 
     */
    T operator[](unsigned i) const
    {
        if (i == 0)
	{ 
		return m_x;
	}
        if (i == 1)
	{	 
		return m_y;
	}
        if (i == 2)
	{ 
		return m_z;
	}
        return m_w;
    }

    T& operator[](unsigned i) 
    {
        if (i == 0) {return m_x;}
        if (i == 1) {return m_y;}
        if (i == 2) {return m_z;}
        return m_w;
    }

    bool Load(File* f);
private :
    T m_w;
    T m_x;
    T m_y;
    T m_z;
};

typedef Vec4<float> Vec4f;
typedef Vec4<int>   Vec4i;

#endif
